#!/bin/bash
set -e
if [ -z "${MountPoint}" ]; then
    EnvFile="../common/0_env.sh"
    # shellcheck source=../common/0_env.sh
    source ${EnvFile}
fi

echo -e "\n***********************************************************************"
echo -e "\t\t$0 : 测试 orcafs-ctl --du --num 统计文件个数"
echo -e "***********************************************************************"

fileNum=10
dirName="/test_du_num"
absDirPath="${MountPoint}${dirName}"

uid=`cat /etc/passwd | grep "${SysUser}" | awk -F: '{print $3}'`
gid=`cat /etc/passwd | grep "${SysUser}" | awk -F: '{print $4}'`

function test_du_num_file()
{
    echo -e "\n\t测试子文件个数 orcafs-ctl --du --num --type=file --path=$1 $3"
    if (($# < 2)); then echo "Invalid args num"; return 1; fi

    dirPath="$1"
    idStr="$3"

    if [ -z "${idStr}" ]; then
        ctl_num=`orcafs-ctl --du --num --type=file "--path=${dirPath}" | awk '{print $8}'`
    else
        ctl_num=`orcafs-ctl --du --num --type=file "--path=${dirPath}" "${idStr}" | awk '{print $8}'`
    fi

    sys_find_num=$2
    echo -e "\t ctl_num=${ctl_num}, sys_find_num=${sys_find_num}"

    compare_num "${ctl_num}" "${sys_find_num}"
}

function test_du_num_dir()
{
    echo -e "\n\t测试子目录个数 orcafs-ctl --du --num --type=dir --path=$1 $3"
    if (($# < 2)); then echo "Invalid args num"; return 1; fi

    dirPath="$1"
    idStr="$3"

    if [ -z "${idStr}" ]; then
        ctl_num=`orcafs-ctl --du --num --type=dir "--path=${dirPath}" | awk '{print $8}'`
    else
        ctl_num=`orcafs-ctl --du --num --type=dir "--path=${dirPath}" "${idStr}" | awk '{print $8}'`
    fi

    sys_find_num=$2
    echo -e "\t ctl_num=${ctl_num}, sys_find_num=${sys_find_num}"

    compare_num "${ctl_num}" "${sys_find_num}"
}

# arg1: dirpath 
# arg2: expect sys_find_num
# arg3: "--uid=x or --gid=x"
# arg4: --parallel
function test_du_num_all()
{
    if (($# < 2)); then 
        echo "The number of parameters must be greater than 1"; return 1; 
    else
        dirPath="$1"
        sys_find_num=$2
        if [ -n "$3" ]; then idStr="$3"; else idStr=""; fi
        if [ -n "$4" ]; then parallelStr="--parallel"; else parallelStr=""; fi
        cmd="orcafs-ctl --du --num --path=${dirPath} ${idStr} ${parallelStr}"
    fi

    echo -e "\n\t测试(子文件+子目录)总个数 ${cmd}"
    ctl_num=`${cmd} | awk '{print $8}'`
    echo -e "\t ctl_num=${ctl_num}, sys_find_num=${sys_find_num}"

    compare_num "${ctl_num}" "${sys_find_num}"
}

function test_du_num_with_gid()
{
    echo -e "\n测试指定 gid 是能否正确大小"
    findEntryNum=`find "${absDirPath}" -gid "${gid}" | wc -l`
    findDirNum=`find "${absDirPath}" -gid "${gid}" -type d | wc -l`
    findFileNum=`find "${absDirPath}" -gid "${gid}" ! -type d | wc -l`

    test_du_num_all "${dirName}" "${findEntryNum}" "--gid=${gid}"
    test_du_num_dir "${dirName}" "${findDirNum}" "--gid=${gid}"
    test_du_num_file "${dirName}" "${findFileNum}" "--gid=${gid}"

    echo -e "\n测试指定 gid 并发获取文件个数"
    test_du_num_all "${dirName}" "${findEntryNum}" "--gid=${gid}" "--parallel"
}

function test_du_num_with_uid()
{
    echo -e "\n测试指定 uid 是能否正确大小"
    findEntryNum=`find "${absDirPath}" -uid "${uid}" | wc -l`
    findDirNum=`find "${absDirPath}" -uid "${uid}" -type d | wc -l`
    findFileNum=`find "${absDirPath}" -uid "${uid}" ! -type d | wc -l`

    test_du_num_all "${dirName}" "${findEntryNum}" "--uid=${uid}"
    test_du_num_dir "${dirName}" "${findDirNum}" "--uid=${uid}"
    test_du_num_file "${dirName}" "${findFileNum}" "--uid=${uid}"

    echo -e "\n测试指定 uid 并发获取文件个数"
    test_du_num_all "${dirName}" "${findEntryNum}" "--uid=${uid}" "--parallel"
}

function test_du_num_without_id()
{
    findEntryNum=`find "${absDirPath}" | wc -l`
    findDirNum=`find "${absDirPath}" -type d | wc -l`
    findFileNum=`find "${absDirPath}" ! -type d | wc -l`

    echo -e "\n测试没有 uid/gid 是能否正确大小"
    test_du_num_all "${dirName}" "${findEntryNum}"
    test_du_num_dir "${dirName}" "${findDirNum}"
    test_du_num_file "${dirName}" "${findFileNum}"

    echo -e "\n测试没有 uid/gid 并发获取文件个数"
    test_du_num_all "${dirName}" "${findEntryNum}" "--parallel"
}

function exec_chown()
{
    for((i=0;i<3;i++)); do
        # 3 files
        chown "${uid}:${gid}" "${absDirPath}/file${i}"
        # 3 dirs, 3 files, 3 hardlinks for those files
        chown -R "${uid}:${gid}" "${absDirPath}/dir${i}"
    done
}

function create_data()
{
    # 构造数据
    echo -e "\n构造数据 ${dirName}"

    for((i=0;i<${fileNum};i++)); do
        # 普通文件 10
        dd if=/dev/zero of="${absDirPath}/file${i}" bs=1000 count=1 &> /dev/null
        # 链接文件 20
        ln -s "${absDirPath}/file${i}" "${absDirPath}/softlink_dir/file${i}_soft"
        ln "${absDirPath}/file${i}" "${absDirPath}/hardlink_dir/file${i}_hard"

        # 隐藏文件 10
        dd if=/dev/zero of="${absDirPath}/.hidden_dir/.file${i}" bs=1000 count=1 &> /dev/null
        
        # 子目录 10
        mkdir -p "${absDirPath}/dir${i}"
        # 子目录的软连接文件 10
        ln -s "${absDirPath}/dir${i}" "${absDirPath}/softlink_dir/dir${i}_soft"
        # 子目录的子文件 10
        dd if=/dev/zero of="${absDirPath}/dir${i}/file${i}" bs=1000 count=1 &> /dev/null
    done

    echo -e "\t注意: 创建后需要 sleep 等待文件系统更新"
    
    totalFile=$[${fileNum}*6]
    echo -e "\t共创建 ${totalFile} files, ${fileNum} + 4 dirs, 其中 20 软连接，10 硬链接"
    sleep 1
}

function init_dir()
{
    rm_abs_dir "${absDirPath}"
    mkdir -p "${absDirPath}"
    orcafs-ctl --setpattern --storagepoolid=2 "${absDirPath}" &> /dev/null
    mkdir -p "${absDirPath}/softlink_dir/"
    mkdir -p "${absDirPath}/hardlink_dir/"
    mkdir -p "${absDirPath}/.hidden_dir/"
}

init_dir
# 测试命令行帮助信息及命令行参数
echo -e "\n测试 orcafs-ctl --du --help"
orcafs-ctl --du --help | grep "\--num"

# 构造数据（文件、目录、硬链接、软连接、隐藏文件）, 并修改部分文件和目录的属性
create_data
exec_chown

# 测试统计整个目录所有子项的个数（不指定和指定 uid/gid）
test_du_num_without_id
test_du_num_with_uid
test_du_num_with_gid

rm_abs_dir "${absDirPath}"